home *** CD-ROM | disk | FTP | other *** search
/ Total Network Tools 2002 / NextStepPublishing-TotalNetworkTools2002-Win95.iso / Archive / Misc Servers / Zope.exe / ZDAEMON.PY < prev    next >
Encoding:
Python Source  |  1999-10-29  |  8.3 KB  |  263 lines

  1. #!/usr/bin/env python
  2. ##############################################################################
  3. # Zope Public License (ZPL) Version 1.0
  4. # -------------------------------------
  5. # Copyright (c) Digital Creations.  All rights reserved.
  6. # This license has been certified as Open Source(tm).
  7. # Redistribution and use in source and binary forms, with or without
  8. # modification, are permitted provided that the following conditions are
  9. # met:
  10. # 1. Redistributions in source code must retain the above copyright
  11. #    notice, this list of conditions, and the following disclaimer.
  12. # 2. Redistributions in binary form must reproduce the above copyright
  13. #    notice, this list of conditions, and the following disclaimer in
  14. #    the documentation and/or other materials provided with the
  15. #    distribution.
  16. # 3. Digital Creations requests that attribution be given to Zope
  17. #    in any manner possible. Zope includes a "Powered by Zope"
  18. #    button that is installed by default. While it is not a license
  19. #    violation to remove this button, it is requested that the
  20. #    attribution remain. A significant investment has been put
  21. #    into Zope, and this effort will continue if the Zope community
  22. #    continues to grow. This is one way to assure that growth.
  23. # 4. All advertising materials and documentation mentioning
  24. #    features derived from or use of this software must display
  25. #    the following acknowledgement:
  26. #      "This product includes software developed by Digital Creations
  27. #      for use in the Z Object Publishing Environment
  28. #      (http://www.zope.org/)."
  29. #    In the event that the product being advertised includes an
  30. #    intact Zope distribution (with copyright and license included)
  31. #    then this clause is waived.
  32. # 5. Names associated with Zope or Digital Creations must not be used to
  33. #    endorse or promote products derived from this software without
  34. #    prior written permission from Digital Creations.
  35. # 6. Modified redistributions of any form whatsoever must retain
  36. #    the following acknowledgment:
  37. #      "This product includes software developed by Digital Creations
  38. #      for use in the Z Object Publishing Environment
  39. #      (http://www.zope.org/)."
  40. #    Intact (re-)distributions of any official Zope release do not
  41. #    require an external acknowledgement.
  42. # 7. Modifications are encouraged but must be packaged separately as
  43. #    patches to official Zope releases.  Distributions that do not
  44. #    clearly separate the patches from the original work must be clearly
  45. #    labeled as unofficial distributions.  Modifications which do not
  46. #    carry the name Zope may be packaged in any form, as long as they
  47. #    conform to all of the clauses above.
  48. # Disclaimer
  49. #   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
  50. #   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  51. #   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  52. #   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
  53. #   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  54. #   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  55. #   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  56. #   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  57. #   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  58. #   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  59. #   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  60. #   SUCH DAMAGE.
  61. # This software consists of contributions made by Digital Creations and
  62. # many individuals on behalf of Digital Creations.  Specific
  63. # attributions are listed in the accompanying credits file.
  64. ##############################################################################
  65. """
  66.  
  67. zinit, slightly smarter server manager and ZServer startup script.
  68.  
  69.   zinit will:
  70.  
  71.     - Fork a parent and a child
  72.  
  73.     - restart the child if it dies
  74.  
  75.     - write a pid file so you can kill (the parent)
  76.  
  77.     - reports the childs pid to stdout so you can kill that too
  78.  
  79. TODO
  80.  
  81.   - Have the parent reap the children when it dies
  82.  
  83.   - etc.
  84.  
  85. """
  86.  
  87. import os, sys, time, signal, posix
  88.  
  89. pyth = sys.executable
  90.  
  91. class KidDiedOnMeError(Exception):
  92.     pass
  93.  
  94. class ExecError(Exception):
  95.     pass
  96.  
  97. class ForkError(Exception):
  98.     pass
  99.  
  100. FORK_ATTEMPTS = 2
  101.  
  102. # This is the number of seconds between the parent pulsing the child.
  103. # Set to 0 to deactivate pulsing.
  104.  
  105. BEAT_DELAY = 0
  106. VERBOSE = 1
  107.  
  108. # If you want the parent to 'pulse' Zope every 'BEAT_DELAY' seconds,
  109. # put the URL to the method you want to call here.  This can be any
  110. # methodish object that can be called through the web.  Format is:
  111. #
  112. # activities = (("http://x/method", "username", "password"),)
  113. #
  114. # username and password may be None if the method does not require
  115. # authentication. 
  116.  
  117. # activities = (('http://localhost:9222/Heart/heart', 'michel', '123'),
  118. #               )
  119.  
  120. import zLOG
  121.  
  122. #this is a bit of a hack so I dont have to change too much code
  123. def pstamp(message, sev):
  124.     zLOG.LOG("zdaemon", sev,
  125.              ("zdaemon: %s: %s" % (time.ctime(time.time()), message)))
  126.  
  127. def heartbeat():
  128.     print 'tha-thump'
  129.     if activities:
  130.         for a in activities:
  131.             try:
  132.                 result = ZPublisher.Client.call(a[0], a[1], a[2])
  133.             except:
  134.                 pstamp('activity %s failed!' % a[0], zLOG.WARNING)
  135.                 return
  136.  
  137.             if result and VERBOSE:
  138.                 pstamp('activity %s returned: %s' % (a[0], result),
  139.                        zLOG.BLATHER)
  140.  
  141.  
  142. def forkit(attempts = FORK_ATTEMPTS):
  143.     while attempts:
  144.         # if at first you don't succeed...
  145.         attempts = attempts - 1
  146.         try:
  147.             pid = os.fork()
  148.         except os.error:
  149.             pstamp('Houston, the fork failed', zLOG.ERROR)
  150.             time.sleep(2)
  151.         else:
  152.             pstamp('Houston, we have forked', zLOG.INFO)
  153.             return pid
  154.  
  155. def run(argv, pidfile=''):
  156.     if os.environ.has_key('ZDAEMON_MANAGED'):
  157.         # We're the child at this point.  Don't ask. :/
  158.  
  159.         return
  160.     
  161.     os.environ['ZDAEMON_MANAGED']='TRUE'
  162.     while 1:
  163.         if not os.environ.has_key('Z_DEBUG_MODE'):
  164.             pid = os.fork()
  165.             if pid:
  166.                 sys.exit(0)
  167.             posix.setsid()
  168.  
  169.         lastt=time.time()
  170.         try:
  171.             pid = forkit()
  172.  
  173.             if pid is None:
  174.                 raise ForkError
  175.  
  176.             elif pid:
  177.                 # Parent 
  178.                 pstamp(('Hi, I just forked off a kid: %s' % pid), zLOG.INFO)
  179.                 # here we want the pid of the parent
  180.                 if pidfile:
  181.                     pf = open(pidfile, 'w+')
  182.                     pf.write(("%s" % os.getpid()))
  183.                     pf.close()
  184.  
  185.                 while 1: 
  186.                     if not BEAT_DELAY:
  187.                         p,s = os.waitpid(pid, 0)
  188.                     else:
  189.                         p,s = os.waitpid(pid, os.WNOHANG)
  190.                         if not p:
  191.                             time.sleep(BEAT_DELAY)
  192.                             heartbeat()
  193.                             continue
  194.                     if s:
  195.                         pstamp(('Aiieee! %s exited with error code: %s' 
  196.                                 % (p, s)), zLOG.ERROR)
  197.                         if time.time()-lastt < 20:
  198.                             raise ForkError # We're probably hosed
  199.                     else:
  200.                         raise ForkError
  201.                         pstamp(('The kid, %s, died on me.' % pid),
  202.                                zLOG.WARNING)
  203.  
  204.                     raise KidDiedOnMeError
  205.  
  206.             else:
  207.                 # Child
  208.                 os.execv(pyth, (pyth,)+tuple(argv))
  209.                 
  210.  
  211.         except ExecError:
  212.             sys.exit()
  213.         except ForkError:
  214.             sys.exit()
  215.         except KidDiedOnMeError:
  216.             pass
  217.  
  218. def main():
  219.     argv=sys.argv[1:]
  220.     if argv and argv[0][:2]=='-p':
  221.         pidf=argv[0][2:]
  222.         del argv[0]
  223.     else:
  224.         pidf=''
  225.  
  226.     if not argv:
  227.         print __doc__ % vars()
  228.         print
  229.         print 'Error: no script given'
  230.             
  231.     run(argv, pidf)
  232.     
  233.  
  234. if __name__ == '__main__': main()
  235.  
  236.  
  237.  
  238.  
  239.  
  240.  
  241.  
  242.